package com.sino.bucket;


import java.util.concurrent.ArrayBlockingQueue;

/**
 * <p>简单漏桶算法实现</p>
 * spring项目使用默认单例模式注入
 * @author yanweihua
 */
public class LeakyBucketHandle<T> {
//	private final  static Logger log = LoggerFactory.getLogger(LeakyBucketHandle.class);

	// 漏水速率/s
	private final int rate;
	private long lastTime = System.currentTimeMillis();
	private final int capacity;
	// 最大并发量（桶最大容量）
	private final ArrayBlockingQueue<T> queue;

	// init
	public LeakyBucketHandle(int rate, int capacity) {
		this.rate = rate;
		this.capacity = capacity;
		this.queue = new ArrayBlockingQueue<T>(capacity);
	}

	public boolean acquire(T b) {
		if (queue.size() > capacity) {
			return false;
		} else {
			queue.offer(b);
			return true;
		}
	}

	public synchronized void consume(CallBackFun<T> callBackFun) throws InterruptedException {
		while (queue.size() > 0) {
			long now = System.currentTimeMillis();
			if ((now-lastTime) > 1000/rate) {
				T t = queue.poll();
//				log.debug("interval-{}-ms", (now-lastTime));
				lastTime = now;
				callBackFun.process(t);
//				log.debug("bucket size is {}", queue.size());
			} else {
				Thread.sleep(1);
			}
		}
	}
}
